#include "experimentrestore.h"
#include "ui_experimentrestore.h"

ExperimentRestore::ExperimentRestore(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ExperimentRestore)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::CustomizeWindowHint|Qt::WindowCloseButtonHint);

    /* 初始化 */
    wlkService = new WLKService();
    experimentService = new ExperimentService();
    cusMsg = new CustomMessageBox();
    ui->deviceName->setPlaceholderText("这里显示所选实验的设备");

    /* 渲染实验列表 */
    this->renderExperimentNameList();

    /* 设备名称不可输入 */
    ui->deviceName->setReadOnly(true);

    /* 隐藏进度条控件 */
    ui->progressBar->hide();
    ui->currentCycling->hide();
    ui->split->hide();
    ui->totalCycling->hide();

    /* 获取实验恢复文件 */
    currentDirPath = QCoreApplication::applicationDirPath();
    currentDir = currentDirPath + "/$expRes";

    /* 根据数据库中的设备id反选设备名称 */
    connect(ui->experimentName, &QComboBox::currentTextChanged, this, [=](QString experimentInfo){
        /* 判断设备是否存在：默认为false */
        this->deviceIsExistence = false;
        /* 通过实验信息获取实验名称 */
        experimentName = experimentInfo.split(" - ")[0];
        //        LOG << experimentInfo.split(" - ");

        /* 获取QVariant的设备 */
        QString deviceId = ui->experimentName->currentData().value<QString>();

        /* 查询设备名称 */
        for(int i = 0; i < connectDeviceInfo.size(); i++){
            if(deviceId == connectDeviceInfo[i].dev.id){
                /* 渲染当前设备id所对应的设备名称 */
                ui->deviceName->setText(connectDeviceInfo[i].dev.name);
                this->deviceIsExistence = true;
            }
        }
        if(!this->deviceIsExistence){
            cusMsg->show(this, CCritical, "实验恢复", "设备不存在！！！");
            ui->deviceName->clear();
        }

    });

    connect(ui->restore, &QPushButton::clicked, this, &ExperimentRestore::restoreExperiment);

}

ExperimentRestore::~ExperimentRestore()
{
    delete ui;
}

/* 渲染实验列表 */
void ExperimentRestore::renderExperimentNameList(){
    ui->experimentName->blockSignals(true);
    ui->experimentName->clear();
    /* 查询满足实验回复条件的设备信息 */
    experimentList = experimentService->getExperimentList();
    /* 渲染 */
    for(int i = 0; i < experimentList.size(); i++){
        /* 写入实验信息 */
        QString experimentInfo = experimentList[i]["experiment_name"] + " - " + experimentList[i]["update_time"];
        /* 写入QVariant：设备id */
        QVariant deviceId;
        deviceId.setValue(experimentList[i]["device_id"]);
        /* 写入ComboBox */
        ui->experimentName->addItem(experimentInfo, deviceId);
    }
    /* 下标-1 */
    ui->experimentName->setCurrentIndex(-1);
    ui->experimentName->blockSignals(false);
}

/* 实验恢复函数 */
void ExperimentRestore::restoreExperiment(){
    /* 判断设备是否存在 */
    if(!this->deviceIsExistence){
        cusMsg->show(this, CCritical, "实验恢复", "设备不存在！！！");
        return;
    }

    /* 判断实验文件是否存在 */
    filePath = currentDir + "/." + experimentName + "_" + ui->deviceName->text() + ".wlk";

    QFile file(filePath);
    if(!file.exists()){
        cusMsg->show(this, CCritical, "实验恢复", "所要恢复的实验不存在！！");
        return;
    }
    cusMsg->show(this, CInformation, "实验恢复", "实验恢复开始");

    this->readyRestoring();
}

/* 预备实验恢复 */
void ExperimentRestore::readyRestoring(){
    /* 所有组件失效 */
    this->allComponentsInvalid();

    /* 获取WLK文件 */
    std::tie(this->wlkImportData, isValid) = wlkService->getWLKData(this->filePath);

    /* 获取并写入实验id */
    this->id = wlkImportData.experimentId;
//    this->id = "";

    LOG << "wlkImportData.experimentId" << wlkImportData.experimentId;

    LOG << "实验恢复数据1111111111111111111111";

    /* 获取循环数 */
    for(int i = 0; i < this->wlkImportData.procedureData.keys().size(); i++){
        if((this->wlkImportData.procedureData.keys()[i])["name"] == "PCR阶段"){
            this->totalCycling = this->wlkImportData.procedureData.keys()[i]["cycle_number"].toInt();
            break;
        }
    }

    /* 渲染循环数 */
    ui->totalCycling->setText(QString::number(this->totalCycling));

    /* 获取当前设备 */
    for(int i = 0; i < connectDeviceInfo.size(); i++){
        if(connectDeviceInfo[i].dev.name == ui->deviceName->text()){
            cDevS = connectDeviceInfo[i];
        }
    }

    this->communicationHuiFu();
}

/* 通信槽函数 */
void ExperimentRestore::communicationHuiFu(){    
    /* 设置进度条最大值 */
    ui->progressBar->setMaximum(this->totalCycling);
    /* 渲染总循环数 */
    ui->totalCycling->setText(QString::number(this->totalCycling));

    LOG << "开始自检";

    /* 第一次恢复，发自检指令，判断设备状态 */
    if(!cDevS.instructionsService->m_socketClient->isConnected()){
        cDevS.instructionsService->establishConnection(cDevS.dev.ip, cDevS.dev.port.toInt());
    }
    this->sleep(EXPERIMENT_RUNNING_SLEEP_TIME);
    /* 发送请求自检命令 */
    cDevS.instructionsService->sendChecking(cDevS.dev.id);
    this->sleep(EXPERIMENT_RUNNING_SLEEP_TIME);
    /* 获取自检信息，判断是否为其他状态 */
    cDevS.msg = cDevS.instructionsService->ziJianData;
    if(cDevS.msg.size() != 0){
        if(!cDevS.msg[2].contains("成功") && !cDevS.msg[2].contains("运行") && cDevS.msg[2].contains("不运行")){
            cusMsg->show(this, CMsg::CCritical, "实验恢复", "设备故障，实验恢复失败！");
            /* 初始化 */
            cDevS.instructionsService->ziJianData.clear();
            return;
        }
    }
    /* 初始化 */
    cDevS.instructionsService->ziJianData.clear();

    LOG << "结束自检";

    LOG << "this->id" << this->id;

    /* 大循环：根据循环数发送指令并获取数据 */
    for(int z = 0; z < this->totalCycling; z++){
        huiFuData.clear();
        cDevS.instructionsService->shiyanHuiFuList.clear();

        /* 判断是否建立链接 */
        if(!cDevS.instructionsService->m_socketClient->isConnected()){
            cDevS.instructionsService->establishConnection(cDevS.dev.ip, cDevS.dev.port.toInt());
        }
        this->sleep(EXPERIMENT_RUNNING_SLEEP_TIME);

        /* 发送通信指令 */
        cDevS.instructionsService->sendShiYanHuiFu(cDevS.dev.id, this->id);
        /* 休眠 */
        this->sleep(EXPERIMENT_RUNNING_SLEEP_TIME);
        /* 获取恢复数据 */
        huiFuData = cDevS.instructionsService->getShiYanHuiFuData();

        if(huiFuData.size() == 1){
            if(huiFuData[0].deviceID == ""){
                cusMsg->show(this, CMsg::CInformation, "实验恢复", "收到实验恢复命令，但命令中无荧光值！");
                /* 清空wlk文件的荧光数据 */
                this->wlkImportData.yingGuangData.clear();
                /* 进一步处理 */
                /* 进行数据分析 */
                /* 渲染组件 */
                this->allComponentsValid();
                /* 清空数据 */
                cDevS.instructionsService->shiyanHuiFuList.clear();
                /* socket回收 */
                if(cDevS.instructionsService->m_socketClient->isConnected()){
                    cDevS.instructionsService->m_socketClient->closeSocket();
                }
                this->close();
                emit ExperimentRestore::analysisExperiment(this->wlkImportData);
                return;
            }
        }

        LOG << "实验恢复数据" << huiFuData.size();

        /* 如果回传数据不为空 */
        if(huiFuData.size() != 0){
            for(int i = 0; i < huiFuData.size(); i++){
                for(int j = 0; j < 32; j++){
                    QHash<QString, QString> sampleWells = huiFuData[i].sample_wells[j];
                    int count = 0;
                    foreach(QString val, sampleWells){
                        if(val == "0") count++;
                    }
                    if(count == 32){
                        cusMsg->show(this, CMsg::CInformation, "实验恢复", "实验恢复无荧光值");

                        /* 进一步处理 */
                        /* 进行数据分析 */
                        /* 渲染组件 */
                        this->allComponentsValid();
                        /* 清空数据 */
                        cDevS.instructionsService->shiyanHuiFuList.clear();
                        /* socket回收 */
                        if(cDevS.instructionsService->m_socketClient->isConnected()){
                            cDevS.instructionsService->m_socketClient->closeSocket();
                        }
                        this->close();
                        emit ExperimentRestore::analysisExperiment(this->wlkImportData);
                        return;
                    }
                    else {
                        sampleWells.clear();
                        count = 0;
                    }
                }
                this->saveYingguangDataList.append(huiFuData[i].sample_wells);
            }
        }
        /* 回传数据为空 */
        else {
            /* 二次回传 */
            /* 判断是否建立链接 */
            if(!cDevS.instructionsService->m_socketClient->isConnected()){
                cDevS.instructionsService->establishConnection(cDevS.dev.ip, cDevS.dev.port.toInt());
            }
            /* 休眠 */
            this->sleep(EXPERIMENT_RUNNING_SLEEP_TIME);
            /* 发送通信指令 */
            cDevS.instructionsService->sendShiYanHuiFu(cDevS.dev.id, this->id);
            /* 休眠 */
            this->sleep(EXPERIMENT_RUNNING_SLEEP_TIME);
            /* 获取恢复数据 */
            huiFuData = cDevS.instructionsService->getShiYanHuiFuData();
            /* 如果回传数据不为空 */
            if(huiFuData.size() != 0){
                for(int i = 0; i < huiFuData.size(); i++){
                    for(int j = 0; j < 32; j++){
                        QHash<QString, QString> sampleWells = huiFuData[i].sample_wells[j];
                        int count = 0;
                        foreach(QString val, sampleWells){
                            if(val == "0") count++;
                        }
                        if(count == 32){
                            cusMsg->show(this, CMsg::CInformation, "实验恢复", "实验恢复无荧光值");
                            /* 进一步处理 */
                            /* 进行数据分析 */
                            this->allComponentsValid();
                            /* 清空数据 */
                            cDevS.instructionsService->shiyanHuiFuList.clear();
                            /* socket回收 */
                            if(cDevS.instructionsService->m_socketClient->isConnected()){
                                cDevS.instructionsService->m_socketClient->closeSocket();
                            }
                            this->close();
                            emit ExperimentRestore::analysisExperiment(this->wlkImportData);
                            return;
                        }
                        else {
                            sampleWells.clear();
                            count = 0;
                        }
                    }
                    this->saveYingguangDataList.append(huiFuData[i].sample_wells);
                }
                /* 进度条增加 */
                ui->progressBar->setValue(z);
                /* 当前循环数增加 */
                ui->currentCycling->setText(QString::number(z));
            }
            /* 二次回传为空 */
            else {
                cusMsg->show(this, CMsg::CCritical, "实验恢复", "实验数据为空，实验恢复失败！");
                this->allComponentsValid();
                /* 清空数据 */
                cDevS.instructionsService->shiyanHuiFuList.clear();
                /* socket回收 */
                if(cDevS.instructionsService->m_socketClient->isConnected()){
                    cDevS.instructionsService->m_socketClient->closeSocket();
                }
                return;
            }
        }

        /* 进度条增加 */
        ui->progressBar->setValue(z+1);
        /* 当前循环数增加 */
        ui->currentCycling->setText(QString::number(z+1));
    }

    qDebug() << "this->saveYingguangDataList" << this->saveYingguangDataList.size() << this->saveYingguangDataList;

    /* 回写荧光数据 */
    this->wlkImportData.yingGuangData = this->saveYingguangDataList;

    /* 进行数据分析 */
    this->allComponentsValid();
    /* 清空数据 */
    cDevS.instructionsService->shiyanHuiFuList.clear();
    /* socket回收 */
    if(cDevS.instructionsService->m_socketClient->isConnected()){
        cDevS.instructionsService->m_socketClient->closeSocket();
    }

    this->sleep(100);

    qDebug() << "发送信号开始";
    emit ExperimentRestore::analysisExperiment(this->wlkImportData);
    qDebug() << "发送信号结束";

    this->close();
}

/* 所有组件失效 */
void ExperimentRestore::allComponentsInvalid(){
    /* 组件失效 */
    ui->restore->setEnabled(false);
    ui->experimentName->setEnabled(false);
    ui->deviceName->setEnabled(false);
    /* 进度条显示 */
    ui->progressBar->show();
    ui->currentCycling->show();
    ui->totalCycling->show();
    ui->split->show();
}

/* 所有组件生效 */
void ExperimentRestore::allComponentsValid(){
    /* 组件生效 */
    ui->restore->setEnabled(true);
    ui->experimentName->setEnabled(true);
    ui->deviceName->setEnabled(true);
    /* 进度条隐藏 */
    ui->progressBar->hide();
    ui->currentCycling->hide();
    ui->totalCycling->hide();
    ui->split->hide();
    /* 进度条初始化 */
    ui->progressBar->setValue(0);
}

/* 休眠函数 */
void ExperimentRestore::sleep(int msec){
    QTime dieTime = QTime::currentTime().addMSecs(msec);
    while( QTime::currentTime() < dieTime )
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

/* 关闭函数 */
void ExperimentRestore::closeEvent(QCloseEvent *event) {
    ui->experimentName->blockSignals(true);
    ui->deviceName->blockSignals(true);

    /* 将实验列表下标设为-1 */
    ui->experimentName->setCurrentIndex(-1);
    /* 清空设备lineEdit */
    ui->deviceName->clear();

    ui->experimentName->blockSignals(false);
    ui->deviceName->blockSignals(false);
}

